package org.raymond.iworks.study.basic.thread.phaser;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Phaser;

/**
 * 多阶段协同器, 一个可重用的同步屏障，在功能上类似于CyclicBarrier和CountDownLatch,但支持更灵活的使用
 * Phaser的灵活性主要体现在在构造函数时不需要强制指定目前有多少参与协作的线程,可以在运行时动态改变
 *
 * Phaser通过status字段来实现同步逻辑,status是一个64位的long变量,它有包含了四个维度的语义:
 * 1、第0-15位,当前未到达的parties,调用arriveXXX时,该值-1,调用register时+1；
 * 2、第16-31位,当前总parties,调用register时+1,deRegister时-1;
 * 3、第32-62位,phase,即Phaser的年龄,当未到达的parties减到0
 * (即所有parties已到达)时,phase自动加1,并且把16-31位的parties数复制到0-15位,从而该Phaser可以继续复用;
 **/
@Slf4j
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        test1();
    }

    // 模拟countdownlatch
    public static void test1() throws InterruptedException {
        Phaser phaser = new Phaser(3);
        Thread t1 = new Thread(()->{
            try {
                log.info("开始工作1");
                Thread.sleep(1000*1);
                log.info("结束工作1");
                phaser.arriveAndDeregister();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread t2 = new Thread(()->{
            try {
                log.info("开始工作2");
                Thread.sleep(1000*2);
                log.info("结束工作2");
                phaser.arriveAndDeregister();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread t3 = new Thread(()->{
            try {
                log.info("开始工作3");
                Thread.sleep(1000*3);
                log.info("结束工作3");
                phaser.arriveAndDeregister();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        t2.start();
        t3.start();

        log.info("开始准备工作");
        phaser.register();
        Thread.sleep(1000*5);
        log.info("准备工作完成");
        phaser.arriveAndAwaitAdvance();
        log.info("所有工作都结束,可以汇总报告了");
    }
    public static void test2(){
        Phaser phaser = new Phaser(1);
        for(int i=0; i<5; i++){
            phaser.register(); //添加一个新的注册者
            final int j = i;
            new Thread(()->{
                log.info("开始工作{}", j);
                try {
                    Thread.sleep(500*j);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("结束工作{}", j);
                phaser.arriveAndAwaitAdvance(); //到达栅栏点，必须等待其他所有注册者到达
            }).start();
        }

        log.info("启动了所有线程");
        phaser.arriveAndDeregister(); //到达栅栏点，注销自己无须等待其他的注册者到达
        log.info("当前线程退出,且parties-1");
    }

    public static void test3(){
        Phaser phaser = new Phaser(1);

        // 给Phaser增加parties，并且可以通过deRegister减少总parties,
        // (CyclicBarrier,CountDownLatch,Semaphore等工具不具备这种灵活性)
        phaser.register();
        new Thread(()->{
            /**
             * 在所有parties都到达之前当前线程处于挂起等待状态,当所有parties都已到达之后线程被唤醒并且Phaser年龄增加,
             * 未到达parties数还原,Phaser复用
             */
            phaser.arriveAndAwaitAdvance();
        }).start();

        phaser.register();
        new Thread(()->{
            phaser.arriveAndAwaitAdvance();
        }).start();

        phaser.arriveAndDeregister();
        log.info("test3 end");
    }

    public static void test4(){
        Phaser phaser = new Phaser(1);

        phaser.register();
        //phaser.register();
        new Thread(()->{
            phaser.arriveAndAwaitAdvance();
        }).start();

        /*
        phaser.register();
        new Thread(()->{
            phaser.arriveAndAwaitAdvance();
        }).start();
         */

        phaser.arriveAndDeregister();
        phaser.arriveAndDeregister();
        log.info("test2 end");
    }
}
